﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using GraphSharp.Controls;
using DFASimulation;

namespace GraphLibrary
{
    public class DFAGraphLayout : GraphLayout<DFAVertex, DFAEdge, DFAGraph> { }

    public class GraphControlViewModel : INotifyPropertyChanged
    {
        private string layoutAlgorithmType;
        private List<String> layoutAlgorithmTypes = new List<string>();
        private DFAGraph graph;
        public List<DFAState> states { get; private set; }
        public List<DFAVertex> vertexStates { get; set; }
        public List<char> rules { get; private set; }
        public List<List<DFAState>> transitions { get; private set; }
        public List<DFAEdge> edgeTransitions { get; private set; }
        private DFAInterface dfainterface;
        public Boolean isReadOnly { get; private set; }

        public DFAGraph Graph
        {
            get { return graph; }
            set
            {
                graph = value;
                NotifyPropertyChanged("Graph");
            }
        }

        public List<String> LayoutAlgorithmTypes
        {
            get { return layoutAlgorithmTypes; }
        }

        public String S
        {
            get { return dfainterface.viewRules(); }
            private set { S = value; }
        }

        public String Q
        {
            get { return dfainterface.viewStates(); }
            private set { S = value; }
        }

        public string LayoutAlgorithmType
        {
            get { return layoutAlgorithmType; }
            set
            {
                layoutAlgorithmType = value;
                NotifyPropertyChanged("LayoutAlgorithmType");
            }
        }

        public GraphControlViewModel(DFAInterface dfainterface)
        {
            this.dfainterface = dfainterface;

            transitions = dfainterface.getTransitions();
            states = dfainterface.getStates();
            rules = dfainterface.getRules();

            vertexStates = new List<DFAVertex>();
            foreach (DFAState state in states)
            {
                bool start=false,fin=false;
                if (dfainterface.startState!=null && dfainterface.startState.id == state.id)
                    start = true;
                foreach (DFAState final in dfainterface.getAcceptStates())
                {
                    if (final.id == state.id)
                    {
                        fin = true;
                        break;
                    }
                }
                vertexStates.Add(new DFAVertex(state.id.ToString(), state.desc, start, fin));
            }

            edgeTransitions = new List<DFAEdge>();
            for (int i = 0; i < states.Count; i++)
            {
                for (int j = 0; j < transitions[i].Count; j++)
                {
                    var dummyState = vertexStates.Single(x => x.id == transitions[i][j].id.ToString());
                    edgeTransitions.Add(new DFAEdge(vertexStates[i], dummyState, rules[j].ToString()));
                }
            }

            Graph = new DFAGraph(true);

            Graph.AddVertexRange(vertexStates);
            Graph.AddEdgeRange(edgeTransitions);

            layoutAlgorithmTypes.Add("BoundedFR");
            layoutAlgorithmTypes.Add("Circular");
            layoutAlgorithmTypes.Add("CompoundFDP");
            layoutAlgorithmTypes.Add("EfficientSugiyama");
            layoutAlgorithmTypes.Add("FR");
            layoutAlgorithmTypes.Add("ISOM");
            layoutAlgorithmTypes.Add("KK");
            layoutAlgorithmTypes.Add("LinLog");
            layoutAlgorithmTypes.Add("Tree");

            LayoutAlgorithmType = "Circular";
            isReadOnly = true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}
